<script setup lang="ts">
import { useLocalStorage } from '@vueuse/core';
import { message } from 'ant-design-vue';
import { assign } from 'lodash-es';
import { io } from 'socket.io-client';
import { computed, onMounted, ref, watch } from 'vue';
import { asyncgettuyaorganizesys } from '../api';
import TuyaiotModel from '../mysql_interface/tuyaiotmodel';
import { Icategory, Ituyalist } from '../tuyav2/interface';
import instruct from './components/instruct.vue';
import state from './components/state.vue';
import {
  DeviceFunctionServiceCommandParam, DeviceFunctionServiceSpecificationResult,
  DeviceServiceDetailResult, DeviceStatusServiceStatusListResult, DeviceStatusServiceStatusParam,
  SpecificationResultFunction, SpecificationResultStatus,
  TuyaGetListParam
} from './interface';

const socket = io('wss://build.hterobot.com/tuyaiot', {
  forceNew: true,
  transports: ["websocket"]
})

const list = ref<DeviceServiceDetailResult[]>([])

const liststate = ref<DeviceStatusServiceStatusListResult[]>([])
const device = ref<DeviceServiceDetailResult>()

const data = ref<TuyaiotModel.ITorganize[]>([])

const form = useLocalStorage('iot-form', {
  phone: '',
  password: ''
})

const dialogFormVisible = ref(false)
const formLabelWidth = ref(120)

const _tuyastate = ref<Icategory[]>([])

// 设备指令\状态 集
const _specificationStatus = ref<SpecificationResultStatus[]>([])
const _specificationFunction = ref<SpecificationResultFunction[]>([])

const tuyalist = ref<Ituyalist[]>([])
const home_id = computed(() => {
  return data.value.find(e => e.phone == form.value.phone)?.home_id
})

onMounted(async () => {
  const data = await fetch('https://cdn-hterobot.oss-cn-qingdao.aliyuncs.com/json/tuyastatev2.json')
  const value: { category: Icategory[], list: Ituyalist[] } = await data.json()
  _tuyastate.value = value.category
  tuyalist.value = value['list']
  if (form.value.password && form.value.phone) {
    submit()
  } else {
    dialogFormVisible.value = true
  }
})


async function submit() {
  if (!form.value.password) {
    message.error('请输入密码')
    return
  }
  if (!form.value.phone) {
    message.error('请输入手机号')
    return
  }
  const n = await asyncgettuyaorganizesys({ password: form.value.password, phone: form.value.phone, })
  if (!n.rows.length) {
    message.error('账号密码不正确')
    return
  }
  data.value = n.rows
  start()
}
const listeners = ref<string[]>([])

function start() {
  socket.on('homes.devices', (..._data) => {
    const _list = []
    for (const data of _data) {
      if (data.success) {
        for (const z of data.result) {
          const f = _list.findIndex(c => c.id === z.id)
          if (f === -1) {
            _list.push(z)
          }
        }
      }
    }
    list.value = _list.sort((a, b) => {
      const t = data.value.find(e => e.phone == form.value.phone)?.v2set?.list.find(z => z.name === a.id)?.conindex || 0
      const t1 = data.value.find(e => e.phone == form.value.phone)?.v2set?.list.find(z => z.name === b.id)?.conindex || 0
      return  t - t1
    })
    getdeviceStatusstatusList(list.value.map(e => e.id))
    for (const v of list.value) {
      const f = listeners.value.includes(v.id)
      if (!f) {
        socket.on(v.id, e => {
          if (e.payload.protocol == 4) {
            getdeviceStatusstatusList([e.payload.data.devId])
          } else {
            if (home_id.value) {
              const devicelistoption: TuyaGetListParam = {
                home_id: home_id.value
              }
              socket.emit('homes.devices', devicelistoption)
            }
          }
        })
        listeners.value.push(v.id)
      }

    }
  })
  socket.on('deviceStatus.statusList', (e) => {
    if (Array.isArray(e.result)) {
      for (const v of e.result) {
        const n = liststate.value.findIndex(z => z.id === v.id)
        if (n > -1) {
          liststate.value.splice(n, 1, assign({}, liststate.value[n], v))
        } else {
          liststate.value.push(v)
        }
      }
    }
  })
  socket.on('deviceStatus.status', (e: {
    data: DeviceStatusServiceStatusParam, devicelistoption: {
      result: {
        code: number,
        t: number,
        status: {
          code: string;
          value: string;
        }[]
      };
    }
  }) => {
    const { devicelistoption, data } = e
    if (devicelistoption.result) {
      const d = liststate.value.find(e => e.id === data.device_id)
      if (d) {
        d.status = devicelistoption.result.status.filter(e => e)
      }
    }
  })
  socket.on('devices.specification', (e: {
    result: DeviceFunctionServiceSpecificationResult
  }) => {
    const { result } = e
    _specificationStatus.value = result.status || []
    _specificationFunction.value = result.functions || []
  })
  socket.on('deviceFunction.commands', e => {
    if (e.success) {
      message.success('发送指令成功')
    } else {
      message.error(e.msg)
    }
  })
  dialogFormVisible.value = false
}

function getdeviceStatusstatusList(data: string[]) {
  const devicelistoption = {
    device_ids: data.join(',')
  }
  socket.emit('deviceStatus.statusList', devicelistoption)
}

function deviceStatusstatus(v: DeviceServiceDetailResult) {
  const devicelistoption: DeviceStatusServiceStatusParam = {
    device_id: v.id
  }
  socket.emit('deviceStatus.status', devicelistoption)
  device.value = v
  socket.emit('devices.specification', devicelistoption)
}

function commands(devicelistoption: DeviceFunctionServiceCommandParam) {
  socket.emit('deviceFunction.commands', devicelistoption)
}


function reload() {
  location.reload()
}


function logout() {
  form.value = { phone: '', password: '' }
  reload()
}

watch(() => home_id.value, e => {
  if (e) {
    const devicelistoption = {
      home_id: e
    }
    socket.emit('homes.devices', devicelistoption)
  }
})


</script>

<template>
  <a-layout class="main-container">
    <a-layout-header class="header" height="96px">
      <div class="header-left">
      </div>
      <div class="header-center">
        物联网设备控制台
      </div>
      <div class="header-right">
        <a-button type="button" @click="logout">退出</a-button>
        <a-button type="button" @click="reload">刷新</a-button>
      </div>
    </a-layout-header>
    <a-layout class="layout-container" style="width: 100%">
      <a-layout-sider width="260" class="aside-left">
        <a-menu>
          <div class="item-title">
            <span>设备列表</span>
          </div>
          <a-menu-item :key="v.id" v-for="v in list" @click="deviceStatusstatus(v)">
            <span class="dian" :class="v.online ? 'online' : 'offline'"></span>
            <span class="lefttext">{{ v.name }}</span>
          </a-menu-item>
        </a-menu>
      </a-layout-sider>
      <a-layout-content class="a-layout-content">
        <instruct :commands="commands" :reset="deviceStatusstatus" v-if="device" :device="device"
          :list="liststate.find(e => e.id === device?.id)" :specificationStatus="_specificationStatus"
          :specificationFunction="_specificationFunction" :tuyastate="_tuyastate">
        </instruct>
      </a-layout-content>
      <div class="aside-right">
        <state class="aside-right-content" v-if="device" :specificationStatus="_specificationStatus"
          :specificationFunction="_specificationFunction" :device="device" :tuyastate="_tuyastate">
        </state>
      </div>
    </a-layout>
    <a-modal v-model:visible="dialogFormVisible" :width="450" title="登录">
      <a-form :model="form">
        <a-form-item label="账号" :label-width="formLabelWidth">
          <a-input v-model:value="form.phone" autocomplete="off" />
        </a-form-item>
        <a-form-item label="密码" :label-width="formLabelWidth">
          <a-input v-model:value="form.password" autocomplete="off" />
        </a-form-item>
      </a-form>
      <template #footer>
        <span class="dialog-footer">
          <a-button @click="dialogFormVisible = false">取消</a-button>
          <a-button type="primary" @click="submit">
            登录
          </a-button>
        </span>
      </template>
    </a-modal>
  </a-layout>
</template>



<style scoped>
.header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, .05);
  background: 000;
  z-index: 1;
}

.header-left,
.header-right {
  width: 200px;
  display: flex;
  justify-content: space-evenly
}

.header-center {
  flex: 1 0 0%;
  text-align: center;
  font-family: 'Arial';
  font-style: normal;
  font-weight: 700;
  font-size: 24px;
}

.main-container {
  min-height: 100vh;
  overflow: hidden;
  background: var(--bg-color);
}

.aside-left .aside-right {
  background: inherit;
  border: none;
}

.aside-left {
  height: calc(100vh - 64px);
  overflow-y: scroll;
}

.aside-right {
  width: calc(100vw - var(--a-layout-content-max-width) - 260px);
}


.layout-container {
  background: inherit;
}

.a-layout-content {
  border-right: 1px solid var(--border-color);
  border-left: 1px solid var(--border-color);
  max-width: var(--a-layout-content-max-width);
  min-width: var(--a-layout-content-mim-width);
  margin-right: 20px;
}

.item-title {
  height: 84px;
  font-size: 24px;
  font-weight: 700;
  border-bottom: 1px solid var(--border-color);
  align-items: center;
  justify-content: center;
  display: flex;
}

.lefttext {
  flex: 1 0 0%;
}

.dian {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  margin: 0 4px;
}

.online {
  background-color: #5fd56b;
}

.offline {
  background-color: rgba(117, 117, 117, 0.4);
}
</style>

<style>
html .main-container {
  --border-color: #e8e8e8;
  --bg-color: rgb(255, 255, 255, 0);
  --a-layout-content-min-width: 200px;
  --a-layout-content-max-width: 500px
}

html .main-container .ant-menu-vertical {
  border-right: none;
}

html .main-container .ant-layout-sider {
  background: none;
}

* {
  padding: 0;
  margin: 0;
}

.flex-grow {
  flex-grow: 1;
}


.box {
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  box-shadow: var(--el-box-shadow-lighter);
}
</style>
